#include "netclient.h"
#include "../model/datacenter.h"
#include <QUuid>
using namespace model;

namespace network
{

NetClient::NetClient(model::DataCenter *dataCenter)
    :dataCenter(dataCenter)
{
    // 不应该在这个环节, 初始化 websocket, 放到 MainWidget 初始化的时候
    //initWebsocket();
}
/////////////////////////////////////////////////////////////////////////////////
/// 下列逻辑都是 http 相关的操作
/////////////////////////////////////////////////////////////////////////////////
void NetClient::ping()
{
    //用http发起ping请求
    QNetworkRequest httpReq;
    httpReq.setUrl(QUrl(HTTP_URL + "/ping"));
    QNetworkReply* httpResp = httpClient.get(httpReq);
    connect(httpResp, &QNetworkReply::finished, this, [=]() {
        // 这里面, 说明响应已经回来了.
        if (httpResp->error() != QNetworkReply::NoError) {
            // 请求失败!
            LOG() << "HTTP 请求失败! " << httpResp->errorString();
            httpResp->deleteLater();
            return;
        }
        // 获取到响应的 body
        QByteArray body = httpResp->readAll();
        LOG() << "响应内容: " << body;
        httpResp->deleteLater();
    });
}
//通过这个函数 把http 请求操作封装一下 避免同质化操作
QNetworkReply *NetClient::sendHttpRequest(const QString &apiPath, const QByteArray &body)
{
    QNetworkRequest httpReq;
    httpReq.setUrl(QUrl(HTTP_URL + apiPath));
    httpReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf");

    QNetworkReply* httpResp = httpClient.post(httpReq, body);
    return httpResp;
}

// 获取当前用户信息
void NetClient::getMyself(const QString &loginSessionId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetUserInfoReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取个人信息]发送获取个人信息请求! requestId: " << req.requestId()  << " sessionId: " << req.sessionId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/get_user_info", body);

    //3. 通过信号槽 获取当前请求的响应 finished信号表示响应已经返回到客户端了
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetUserInfoRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取个人信息] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //把相应的数据 保存到 DataCenter 里
                dataCenter->resetMyself(resp);

                //通知调用逻辑 响应处理完了 仍然通过信号槽 通知
                emit dataCenter->getMyselfDone();

                //debug
                LOG() << "[HTTP获取个人信息] 人信息响应处理完毕! requestId: " << resp->requestId()
                      << " userId: " << resp->userInfo().userId()
                      << " username: " << resp->userInfo().nickname();
            });
}

void NetClient::getFriendList(const QString &loginSessionId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetFriendListReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取好友列表]发送获取好友列表请求! requestId: " << req.requestId()  << " sessionId: " << req.sessionId();
    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_friend_list", body);
    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetFriendListRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取好友列表] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                // 4.把相应的数据 保存到 DataCenter 里
                dataCenter->resetFriendList(resp);

                // 5.通知调用逻辑 响应处理完了 仍然通过信号槽 通知
                emit dataCenter->getFriendListDone();

                //debug
                LOG() << "[HTTP获取好友列表] 好友列表响应处理完毕! requestId: " << resp->requestId();
            });


}

void NetClient::getChatSessionList(const QString &loginSessionId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetChatSessionListReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取会话列表]发送获取会话列表请求! requestId: " << req.requestId()  << " sessionId: " << req.sessionId();
    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_chat_session_list", body);
    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetChatSessionListRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取会话列表] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                // 4.把相应的数据 保存到 DataCenter 里
                dataCenter->resetChatSessionList(resp);

                // 5.通知调用逻辑 响应处理完了 仍然通过信号槽 通知
                emit dataCenter->getChatSessionListDone();

                //debug
                LOG() << "[HTTP获取会话列表] 会话列表响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::getFriendApplyList(const QString &loginSessionId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetPendingFriendEventListReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取好友申请列表]发送获取好友申请列表请求! requestId: " << req.requestId()  << " sessionId: " << req.sessionId();
    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_pending_friend_events", body);
    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetPendingFriendEventListRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取好友申请列表] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                // 4.把相应的数据 保存到 DataCenter 里
                dataCenter->resetFriendApplyList(resp);

                // 5.通知调用逻辑 响应处理完了 仍然通过信号槽 通知
                emit dataCenter->getFriendApplyListDone();

                //debug
                LOG() << "[HTTP获取好友申请列表] 好友申请列表响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::getRecentMessage(const QString &loginSessionId, const QString &chatSessionId, bool updateUI)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetRecentMsgReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setMsgCount(50);
    req.setChatSessionId(chatSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取最近消息列表]发送获取最近消息列表请求! requestId: " << req.requestId()  << " sessionId: " << req.sessionId()
          << " chatSessionId: " << req.chatSessionId();
    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/message_storage/get_recent", body);
    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetRecentMsgRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取最近消息列表] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                // 4.把相应的数据 保存到 DataCenter 里
                dataCenter->resetRecentMessage(chatSessionId, resp);

                // 5.通知调用逻辑 响应处理完了 仍然通过信号槽 通知
                if(updateUI)
                    emit dataCenter->getRecentMessageDone(chatSessionId);
                else
                    emit dataCenter->getRecentMessageNoUIDone(chatSessionId);
                //debug
                LOG() << "[HTTP获取最近消息列表] 最近消息列表响应处理完毕! requestId: " << resp->requestId()
                      << " chatSessionId: " << req.chatSessionId();
            });
}
//extraInfo 文件名
void NetClient::sendMessage(const QString &loginSessionId, const QString &chatSessionId,
                            const model::Message_Type messageType, const QByteArray &content, const QString& extraInfo)
{
    //1. 构造HTTP 请求 Body部分
    xchat::NewMessageReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    //根据messageType 构建不同类型请求
    xchat::MessageContent messageContent;
    if(messageType == model::Message_Type::TEXT_TYPE)
    {
        LOG() << "准备发送文本消息 内容=" << content.constData();
        //这里是protobuf里面定义的MessagType
        messageContent.setMessageType(xchat::MessageTypeGadget::MessageType::STRING);
        xchat::StringMessageInfo stringMessageInfo;
        stringMessageInfo.setContent(content.constData());
        messageContent.setStringMessage(stringMessageInfo);
        req.setMessage(messageContent);
    }
    else if (messageType == model::Message_Type::IMAGE_TYPE)
    {
        LOG() << "准备发送图片消息 大小=" << content.size();
        messageContent.setMessageType(xchat::MessageTypeGadget::MessageType::IMAGE);
        LOG() << "文件类型 " <<  messageContent.messageType();

        xchat::ImageMessageInfo imageMessageInfo;
        imageMessageInfo.setFileId("");			// fileId 是文件在服务器存储的时候, 生成的 id, 此时还无法获取到, 暂时填成 ""
        imageMessageInfo.setImageContent(content);
        messageContent.setImageMessage(imageMessageInfo);
    }
    else if (messageType == Message_Type::FILE_TYPE)
    {
        LOG() << "准备发送文件消息 大小=" << content.size() << " 文件名=" << extraInfo;
        messageContent.setMessageType(xchat::MessageTypeGadget::MessageType::FILE);

        xchat::FileMessageInfo fileMessageInfo;
        fileMessageInfo.setFileId(""); 			// fileId 是文件在服务器存储的时候, 生成的 id, 此时还无法获取到, 暂时填成 ""
        fileMessageInfo.setFileSize(content.size());
        fileMessageInfo.setFileName(extraInfo);
        fileMessageInfo.setFileContents(content);
        messageContent.setFileMessage(fileMessageInfo);
    }
    else if (messageType == Message_Type::SPEECH_TYPE)
    {
        LOG() << "准备发送语音消息 大小=" << content.size();
        messageContent.setMessageType(xchat::MessageTypeGadget::MessageType::SPEECH);

        xchat::SpeechMessageInfo speechMessageInfo;
        speechMessageInfo.setFileId(""); 			// fileId 是文件在服务器存储的时候, 生成的 id, 此时还无法获取到, 暂时填成 ""
        speechMessageInfo.setFileContents(content);
        messageContent.setSpeechMessage(speechMessageInfo);
    }
    else
    {
        LOG() << "错误的消息类型! messageType=" << messageType;
    }
    req.setMessage(messageContent);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP发送消息]发送发送消息请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " chatSessionId: " << req.chatSessionId()
          << " messageType: " << req.message().messageType();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/message_transmit/new_message", body);
    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::NewMessageRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP发送消息] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //不需要把相应数据 保存到 DataCenter 里 发送消息不需要保存响应数据

                //为了把消息展示到界面上 需要把发送的消息也传递回去
                //通知调用逻辑 响应处理完了 仍然通过信号槽
                emit dataCenter->sendMessageDone(messageType, content, extraInfo);

                //debug
                LOG() << "[HTTP发送消息] 发送消息响应处理完毕! requestId: " << resp->requestId();

            });
}

void NetClient::receiveMessage(const QString &chatSessionId)
{
    //1.先判定 收到消息的会话 是否正在被展示
    QString currentChatSessionId = dataCenter->getCurrentChatSessionId();
    bool isCurrentSession = (currentChatSessionId == chatSessionId);

    if(isCurrentSession) //  当前会话 就要把消息显示到消息展示区 也需要更新会话列表的消息预览
    {
        const Message& lastMessage = dataCenter->getRecentMessage(chatSessionId)->back();
        //通知消息展示区 添加新消息
        LOG() << "NetClient::receiveMessage -> lassMessage.chatSessionID" << lastMessage.chatSessionID
              << QString(lastMessage.content);
        emit dataCenter->receiveMessageDone(lastMessage);
    }
    else  //  不是当前会话 只需要更新消息预览 并且更新 “未读消息数目”
    {
        dataCenter->addUnread(chatSessionId);
    }

    emit dataCenter->updateLastMessage(chatSessionId);
}

void NetClient::changeNickname(const QString &loginSessionId, const QString &newNickname)
{
    //1. 构造HTTP 请求 Body部分
    xchat::SetUserNicknameReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setNickname(newNickname);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP修改用户昵称]发送修改用户昵称请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " newNickname: " << req.nickname();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_nickname", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::SetUserNicknameRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP修改用户昵称] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //将新的昵称保存到 DataCenter 里
                dataCenter->resetNickname(newNickname);
                emit dataCenter->changeNicknameDone();

                //debug
                LOG() << "[HTTP修改用户昵称] 修改用户昵称响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::changeDescription(const QString &loginSessionId, const QString &newDescription)
{
    //1. 构造HTTP 请求 Body部分
    xchat::SetUserDescriptionReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setDescription(newDescription);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP修改用户签名]发送修改用户签名请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " newDescription: " << req.description();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_description", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::SetUserDescriptionRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP修改用户签名] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //将新的签名保存到 DataCenter 里
                dataCenter->resetDescription(newDescription);
                emit dataCenter->changeDescriptionDone();

                //debug
                LOG() << "[HTTP修改用户签名] 修改用户签名响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::getVerifyCode(const QString &phoneNumber)
{
    //1. 构造HTTP 请求 Body部分
    xchat::PhoneVerifyCodeReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phoneNumber);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取验证码]发送获取验证码请求! requestId: " << req.requestId()
          << " phoneNumber: " << req.phoneNumber();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/get_phone_verify_code", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::PhoneVerifyCodeRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取验证码] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetVerifyCodeId(resp->verifyCodeId());
                LOG() << "NetClient::getVerifyCode -> verifyCodeId:" << resp->verifyCodeId();

                emit dataCenter->getVerifyCodeDone();

                //debug
                LOG() << "[HTTP获取验证码] 获取验证码响应处理完毕! requestId: " << resp->requestId()
                      << "resp->verifyCodeId: " << resp->verifyCodeId();
            });
}

void NetClient::changePhoneNumber(const QString &loginSessionId, const QString &newPhoneNumber, const QString &verifyCodeId, const QString &userInputCode)
{
    //1. 构造HTTP 请求 Body部分
    xchat::SetUserPhoneNumberReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setPhoneNumber(newPhoneNumber);
    LOG() << "NetClient::changePhoneNumber -> verifyCodeId:" << verifyCodeId << " userInputCode:" << userInputCode;
    req.setPhoneVerifyCodeId(verifyCodeId);
    req.setPhoneVerifyCode(userInputCode);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP修改手机号]发送修改手机号请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " newPhoneNumber: " << req.phoneNumber()
          << " verifyCodeId: " << req.phoneVerifyCodeId()
          << " userInputCode: " << req.phoneVerifyCode();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_phone", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::SetUserPhoneNumberRsp>(httpResp, &ok, &reason);
                if (!ok)
                {
                    // 请求失败
                    LOG() << "[HTTP修改手机号] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetPhoneNumber(newPhoneNumber);
                emit dataCenter->changePhoneNumberDone();

                //debug
                LOG() << "[HTTP修改手机号] 修改手机号响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::changeAvatar(const QString &loginSessionId, const QByteArray &newAvatarData)
{
    //1. 构造HTTP 请求 Body部分
    xchat::SetUserAvatarReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setAvatar(newAvatarData);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP修改头像]发送修改头像请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_avatar", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::SetUserAvatarRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP修改头像] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetAvatar(newAvatarData);

                emit dataCenter->changeAvatarDone();

                //debug
                LOG() << "[HTTP修改头像] 修改头像响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::deleteFriend(const QString &loginSessionId, const QString &friendUserId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::FriendRemoveReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setPeerId(friendUserId);    //网关身份鉴权后能拿到userId
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP删除好友]发送删除好友请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " friendUserId: " << req.peerId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/remove_friend", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::FriendRemoveRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP删除好友] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->removeFriend(friendUserId);

                emit dataCenter->deleteFriendDone();

                //debug
                LOG() << "[HTTP删除好友] 删除好友响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::addFriendApply(const QString &loginSessionId, const QString &friendUserId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::FriendAddReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    LOG() << "NetClient::addFriendApply -> friendUserId:" << friendUserId;
    req.setRespondentId(friendUserId);    //网关身份鉴权后能拿到userId
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP添加好友申请]发送添加好友申请请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " friendUserId: " << req.respondentId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_apply", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::FriendAddRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP添加好友申请] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                emit dataCenter->addFriendApplyDone();

                //debug
                LOG() << "[HTTP添加好友申请] 添加好友申请响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::acceptFriendApply(const QString &loginSessionId, const QString &friendUserId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::FriendAddProcessReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setApplyUserId(friendUserId);    //网关身份鉴权后能拿到userId
    req.setAgree(true);          //同意添加好友
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP接受好友申请]发送接受好友申请请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " friendUserId: " << req.applyUserId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_process", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::FriendAddProcessRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP接受好友申请] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //删除好友申请
                UserInfo appluUser = dataCenter->removeFriendApply(friendUserId);
                //添加好友到好友列表
                QList<UserInfo>* friendList = dataCenter->getFriendList();
                friendList->push_front(appluUser);

                emit dataCenter->acceptFriendApplyDone();

                //debug
                LOG() << "[HTTP接受好友申请] 接受好友申请响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::rejectFriendApply(const QString &loginSessionId, const QString &friendUserId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::FriendAddProcessReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setApplyUserId(friendUserId);    //网关身份鉴权后能拿到userId
    req.setAgree(false);          //拒绝添加好友
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP拒绝好友申请]发送拒绝好友申请请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " friendUserId: " << req.applyUserId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_process", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::FriendAddProcessRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP拒绝好友申请] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //删除好友申请
                dataCenter->removeFriendApply(friendUserId);

                emit dataCenter->rejectFriendApplyDone();

                //debug
                LOG() << "[HTTP拒绝好友申请] 拒绝好友申请响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::createGroupChatSession(const QString &loginSessionId, const QList<QString> &memberUserIds)
{
    //1. 构造HTTP 请求 Body部分
    xchat::ChatSessionCreateReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionName("Xiang家群聊");
    req.setMemberIdList(memberUserIds);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP创建群聊会话]发送创建群聊会话请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " memberUserIds size: " << req.memberIdList().size();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/create_chat_session", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::ChatSessionCreateRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP创建群聊会话] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                emit dataCenter->createGroupChatSessionDone();

                //debug
                LOG() << "[HTTP创建群聊会话] 创建群聊会话响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::getMemberList(const QString &loginSessionId, const QString &chatSessionId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetChatSessionMemberReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取会话成员列表]发送获取会话成员列表请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " chatSessionId: " << req.chatSessionId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_chat_session_member", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetChatSessionMemberRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取会话成员列表] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetChatSessionMemberList(chatSessionId, resp->memberInfoList());

                emit dataCenter->getMemberListDone(chatSessionId);

                //debug
                LOG() << "[HTTP获取会话成员列表] 获取会话成员列表响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::searchUser(const QString &loginSessionId, const QString &keyword)
{
    //1. 构造HTTP 请求 Body部分
    xchat::FriendSearchReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setSearchKey(keyword);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP搜索用户]发送搜索用户请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " keyword: " << req.searchKey();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/search_friend", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::FriendSearchRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP搜索用户] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetSearchUserList(resp->userInfo());

                emit dataCenter->searchUserDone();

                //debug
                LOG() << "[HTTP搜索用户] 搜索用户响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::searchHistoryMessage(const QString &loginSessionId, const QString& chatSessionId, const QString &keyword)
{
    //1. 构造HTTP 请求 Body部分
    xchat::MsgSearchReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    req.setSearchKey(keyword);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP搜索历史消息]发送搜索历史消息请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " keyword: " << req.searchKey();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/message_storage/search_history", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::MsgSearchRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP搜索历史消息] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetSearchMessageList(resp->msgList());

                emit dataCenter->searchHistoryMessageDone();

                //debug
                LOG() << "[HTTP搜索历史消息] 搜索历史消息响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::searchHistoryMessageByTime(const QString &loginSessionId, const QString& chatSessionId, const QDateTime &begTime, const QDateTime &endTime)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetHistoryMsgReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setChatSessionId(chatSessionId);
    req.setStartTime(begTime.toSecsSinceEpoch());
    req.setOverTime(endTime.toSecsSinceEpoch());
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP按时间搜索历史消息]发送按时间搜索历史消息请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " begTime: " << req.startTime()
          << " endTime: " << req.overTime();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/message_storage/get_history", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetHistoryMsgRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP按时间搜索历史消息] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                dataCenter->resetSearchMessageList(resp->msgList());

                emit dataCenter->searchHistoryMessageDone();

                //debug
                LOG() << "[HTTP按时间搜索历史消息] 按时间搜索历史消息响应处理完毕! requestId: " << resp->requestId();
            });
}

void NetClient::userLogin(const QString &userName, const QString &password)
{
    //1. 构造HTTP 请求 Body部分
    xchat::UserLoginReq req;
    req.setRequestId(makeRequestId());
    req.setNickname(userName);
    req.setPassword(password);
    req.setVerifyCode("");
    req.setVerifyCodeId("");
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP用户登录]发送用户登录请求! requestId: " << req.requestId()
          << " userName: " << req.nickname();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/username_login", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::UserLoginRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP用户登录] error ! requestID = " << req.requestId() << "reason: " << reason;
                    emit dataCenter->userLoginDone(false, reason);
                    return;
                }

                //保存登录态到 DataCenter 里
                dataCenter->resetLoginSessionId(resp->loginSessionId());
                emit dataCenter->userLoginDone(true, "");

                //debug
                LOG() << "[HTTP用户登录] 用户登录响应处理完毕! requestId: " << resp->requestId();
    });
}

void NetClient::userRegister(const QString &userName, const QString &password)
{
    //1. 构造HTTP 请求 Body部分
    xchat::UserRegisterReq req;
    req.setRequestId(makeRequestId());
    req.setNickname(userName);
    req.setPassword(password);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP用户注册]发送用户注册请求! requestId: " << req.requestId()
          << " userName: " << req.nickname();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/username_register", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::UserRegisterRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP用户注册] error ! requestID = " << req.requestId() << "reason: " << reason;
                    emit dataCenter->userRegisterDone(false, reason);
                    return;
                }

                emit dataCenter->userRegisterDone(true, "");

                //debug
                LOG() << "[HTTP用户注册] 用户注册响应处理完毕! requestId: " << resp->requestId();
    });
}

void NetClient::phoneLogin(const QString &phoneNumber, const QString& verifyCodeId, const QString &verifyCode)
{
    //1. 构造HTTP 请求 Body部分
    xchat::PhoneLoginReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phoneNumber);
    req.setVerifyCodeId(verifyCodeId);
    req.setVerifyCode(verifyCode);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP手机号登录]发送手机号登录请求! requestId: " << req.requestId()
          << " phoneNumber: " << req.phoneNumber();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/phone_login", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::PhoneLoginRsp>(httpResp, &ok, &reason);
                if (!ok)
                {
                    // 请求失败
                    LOG() << "[HTTP手机号登录] error ! requestID = " << req.requestId() << "reason: " << reason;
                    emit dataCenter->phoneLoginDone(false, reason);
                    return;
                }

                //保存登录态到 DataCenter 里
                dataCenter->resetLoginSessionId(resp->loginSessionId());
                emit dataCenter->phoneLoginDone(true, "");

                //debug
                LOG() << "[HTTP手机号登录] 手机号登录响应处理完毕! requestId: " << resp->requestId();
    });
}

void NetClient::phoneRegister(const QString &phoneNumber, const QString &verifyCodeId, const QString &verifyCode)
{
    //1. 构造HTTP 请求 Body部分
    xchat::PhoneRegisterReq req;
    req.setRequestId(makeRequestId());
    req.setPhoneNumber(phoneNumber);
    req.setVerifyCodeId(verifyCodeId);
    req.setVerifyCode(verifyCode);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP手机号注册]发送手机号注册请求! requestId: " << req.requestId()
          << " phoneNumber: " << req.phoneNumber();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/user/phone_register", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::PhoneRegisterRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP手机号注册] error ! requestID = " << req.requestId() << "reason: " << reason;
                    emit dataCenter->phoneRegisterDone(false, reason);
                    return;
                }

                emit dataCenter->phoneRegisterDone(true, "");

                //debug
                LOG() << "[HTTP手机号注册] 手机号注册响应处理完毕! requestId: " << resp->requestId();
    });
}

void NetClient::getSingleFile(const QString &loginSessionId, const QString &fileId)
{
    //1. 构造HTTP 请求 Body部分
    xchat::GetSingleFileReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setFileId(fileId);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP获取单个文件]发送获取单个文件请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " fileId: " << req.fileId();

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/file/get_single_file", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::GetSingleFileRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP获取单个文件] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                //涉及文件可能有点多 不在datacenter里存了
                //直接通过信号把文件数据投送到调用者位置上
                emit dataCenter->getSingleFileDone(fileId, resp->fileData().fileContent());

                //debug
                LOG() << "[HTTP获取单个文件] 获取单个文件响应处理完毕! requestId: " << resp->requestId();
    });
}

void NetClient::speechToText(const QString &loginSessionId, const QString &fileId, const QByteArray &speechData)
{
    //1. 构造HTTP 请求 Body部分
    xchat::SpeechRecognitionReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    req.setSpeechContent(speechData);
    QByteArray body = req.serialize(&serializer);
    LOG() << "[HTTP语音转文字]发送语音转文字请求! requestId: " << req.requestId()
          << " sessionId: " << req.sessionId()
          << " fileId: " << fileId;

    //2. 构造http请求并发送
    QNetworkReply* httpResp = sendHttpRequest("/service/speech/speech_recognition", body);

    //3. 通过信号槽 获取当前请求的响应
    connect(httpResp, &QNetworkReply::finished, this, [=]()
            {
                // 这里面, 说明响应已经回来了.
                bool ok = false;
                QString reason;
                auto resp = handleHttpResponse<xchat::SpeechRecognitionRsp>(httpResp, &ok, &reason);
                if (!ok) {
                    // 请求失败
                    LOG() << "[HTTP语音转文字] error ! requestID = " << req.requestId() << "reason: " << reason;
                    return;
                }

                emit dataCenter->speechToTextDone(fileId, resp->recognitionResult());

                //debug
                LOG() << "[HTTP语音转文字] 语音转文字响应处理完毕! requestId: " << resp->requestId();
    });
}



/////////////////////////////////////////////////////////////////////////////////
/// 下列逻辑都是 Websocket 相关的操作
/////////////////////////////////////////////////////////////////////////////////
void NetClient::initWebsocket()
{
    // 1. 准备好所有需要的信号槽
    connect(&websocketClient, &QWebSocket::connected, this, [=]() {
        LOG() << "websocket 连接成功!";
        // 不要忘记! 在 websocket 连接成功之后, 发送身份认证消息!
        sendAuth();
    });

    connect(&websocketClient, &QWebSocket::disconnected, this, [=]() {
        LOG() << "websocket 连接断开!";
    });

    connect(&websocketClient, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error) {
        LOG() << "websocket 连接出错!" << error;
    });

    connect(&websocketClient, &QWebSocket::textMessageReceived, this, [=](const QString& message) {
        LOG() << "websocket 收到文本消息!" << message;
    });

    connect(&websocketClient, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray) {
        LOG() << "websocket 收到二进制消息!" << byteArray.length();
        xchat::NotifyMessage notifyMessage;
        bool ok = notifyMessage.deserialize(&serializer, byteArray);
        if (!ok)
        {
            LOG() << "websocket 收到的 NotifyMessage 反序列化失败!";
            return;
        }
        // 处理websocket请求
        handleWebsocketNotifyMessage(notifyMessage);

    });

    // 2. 和服务器真正建立连接
    websocketClient.open(WEBSOCKET_URL);
}
void NetClient::sendAuth()
{
    xchat::ClientAuthenticationReq req;
    req.setRequestId("12345321234");
    req.setSessionId(dataCenter->getLoginSessionId());
    QByteArray body = req.serialize(&serializer);
    websocketClient.sendBinaryMessage(body);
    //debug
    LOG() << "[WS身份认证]发送身份认证请求 !requestId: " << req.requestId()  << " sessionId: " << req.sessionId();

}

void NetClient::handleWebsocketNotifyMessage(const xchat::NotifyMessage& notifyMessage)
{
    // 根据不同的 NotifyMessageType, 进行不同的处理
    if (notifyMessage.notifyType() == xchat::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY)
    {
        //1.把pb中的messageInfo换成自己的Message
        Message message;
        message.load(notifyMessage.newMessageInfo().messageInfo());
        //2.针对自己的Message做进一步的处理
        handleWebsocketMessage(message);
    }
    else if(notifyMessage.notifyType() == xchat::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY)
    {
        ChatSessionInfo chatSessionInfo;
        chatSessionInfo.load(notifyMessage.newChatSessionInfo().chatSessionInfo());
        handleWebsocketCreateGroupChatSession(chatSessionInfo);
    }
    else if(notifyMessage.notifyType() == xchat::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY)
    {
        //收到好友申请通知 后台加载好友申请列表
        LOG() << "[WS好友申请通知] 收到好友申请通知! 后台加载数据 ";
        UserInfo friendApplyUserInfo;
        friendApplyUserInfo.load(notifyMessage.friendAddApply().userInfo());
        handleWebsocketAddFriendApply(friendApplyUserInfo);
    }
    else if(notifyMessage.notifyType() == xchat::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY)
    {
        bool isAccepted = notifyMessage.friendProcessResult().agree();
        UserInfo fromUserInfo;
        fromUserInfo.load(notifyMessage.friendProcessResult().userInfo());
        handleWebsocketFriendApplyProcess(fromUserInfo, isAccepted);
    }
    else if(notifyMessage.notifyType() == xchat::NotifyTypeGadget::NotifyType::FRIEND_REMOVE_NOTIFY)
    {
        const QString& removedFriendUserId = notifyMessage.friendRemove().userId();
        handleWebsocketRemoveFriend(removedFriendUserId);
    }
    else
    {
        LOG() << "[WS新消息通知] 未知的 "<< " notifyType=" << notifyMessage.notifyType();
        return;
    }
}

void NetClient::handleWebsocketMessage(const model::Message &message)
{
    //考虑两个情况
    QList<Message>* msgList = dataCenter->getRecentMessage(message.chatSessionID);
    if(msgList == nullptr) //1. 如果当前这个消息所属的会话没有在 DataCenter 里, 说明是一个新的会话没有chatsessionID 需要先通过网络加载整个消息列表
    {

        LOG() << "[WS新消息通知] 新消息所属会话不存在! 后台加载数据 chatSessionID=" << message.chatSessionID;
        //需要通过网络加载整个消息列表
        connect(dataCenter, &DataCenter::getRecentMessageNoUIDone, this, &NetClient::receiveMessage, Qt::UniqueConnection);
        dataCenter->getRecentMessageAsync(message.chatSessionID, false);
    }
    else     //2. 如果当前这个消息所属的会话已经在 DataCenter 里, 直接把消息 尾插到对应会话的消息列表里
    {
        //情况2: 当前这个消息所属的会话已经在 DataCenter 里
        msgList->push_back(message);
        this->receiveMessage(message.chatSessionID);
    }


}

void NetClient::handleWebsocketRemoveFriend(const QString &removedFriendUserId)
{
    LOG() << "[WS删除好友通知] 收到删除好友通知! removedFriendUserId=" << removedFriendUserId;

    //1.删除数据 datacenter的好友列表
    dataCenter->removeFriend(removedFriendUserId);
    //2.通知界面更新
    emit dataCenter->deleteFriendDone();
}

void NetClient::handleWebsocketAddFriendApply(const model::UserInfo& fromUserInfo)
{
    LOG() << "[WS好友申请通知] 收到好友申请通知! fromUserId=" << fromUserInfo.userID;

    //1.把好友申请添加到 datacenter的好友申请列表
    QList<UserInfo>* friendApplyList = dataCenter->getFriendApplyList();
    if(friendApplyList == nullptr)
    {
        LOG() << "[WS好友申请通知] 好友申请列表不存在! ";
        return;
    }
    friendApplyList->push_front(fromUserInfo);
    //2.通知界面更新
    emit dataCenter->receiveFriendApplyDone();
}

void NetClient::handleWebsocketFriendApplyProcess(const model::UserInfo& fromUserInfo, bool isAccepted)
{
    LOG() << "[WS好友申请处理通知] 收到好友申请处理通知! fromUserId=" << fromUserInfo.userID
          << " isAccepted=" << isAccepted;

    if(isAccepted)
    {
        //1.添加好友到好友列表
        QList<UserInfo>* friendList = dataCenter->getFriendList();
        if(friendList == nullptr)
        {
            LOG() << "[WS好友申请处理通知] 好友列表不存在! ";
            return;
        }
        friendList->push_front(fromUserInfo);

        //更新界面
        emit dataCenter->receiveFriendProcessDone(fromUserInfo.nickname, isAccepted);
    }
    else
    {
        //更新界面
        emit dataCenter->receiveFriendProcessDone(fromUserInfo.nickname, isAccepted);
    }

}

void NetClient::handleWebsocketCreateGroupChatSession(const model::ChatSessionInfo &newSessionInfo)
{
    LOG() << "[WS创建群聊会话通知] 收到创建群聊会话通知! chatSessionID=" << newSessionInfo.chatSessionID;

    //1.把新群聊会话添加到 datacenter的会话列表
    QList<ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();
    if(chatSessionList == nullptr)
    {
        LOG() << "[WS创建群聊会话通知] 会话列表不存在! ";
        return;
    }
    chatSessionList->push_front(newSessionInfo);
    //2.通知界面更新
    emit dataCenter->receiveCreateGroupChatSessionDone(newSessionInfo.chatSessionName);
}



QString NetClient::makeRequestId()
{
    return "R" + QUuid::createUuid().toString().sliced(25, 12);
}

}// namespace network














